package widgets

import (
	"reflect"
	"strings"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/widget"
	"github.com/gogf/gf/v2/container/garray"
	"github.com/gogf/gf/v2/container/gmap"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/util/gconv"
	"github.com/tidwall/gjson"
	"github.com/y2h/fyne_poem/dbb"
	"github.com/y2h/fyne_poem/menu"
)

// 用list显示gdb.Result
func ListResult(newDb gdb.DB, tbl string, rs gdb.Result, msg *widget.Label, w fyne.Window) *widget.List {
	// _, header := dbb.SqliteTblColsGF(newDb, tbl)
	g0 := gjson.Parse(gconv.String(rs[0]))
	header := []string{}
	// 表的列结构体类型
	g0.ForEach(func(key, value gjson.Result) bool {
		header = append(header, key.String())
		return true
	})
	// fmt.Printf("gconv.String(rs[0]): %v\n", gconv.String(rs[0]))
	ldd := len(header)
	// fmt.Printf("ldd: %v\n", ldd)
	var lst *widget.List
	lst = widget.NewList(func() int {
		return rs.Len()
	}, func() fyne.CanvasObject {
		hbox1 := container.NewGridWithColumns(ldd + 2)
		for i := 0; i < ldd; i++ {
			lbl := widget.NewLabelWithStyle("table", fyne.TextAlignCenter,
				fyne.TextStyle{})
			lbl.Wrapping = fyne.TextTruncate
			lbl.SetText((header)[i])
			hbox1.Add(lbl)
		}
		//hbox1.Add(PopUpBtn(nil, w))
		hbox1.Add(widget.NewButton("edit", nil))
		hbox1.Add(widget.NewButton("delete", nil))
		return hbox1
	}, func(lii widget.ListItemID, co fyne.CanvasObject) {
		box := co.(*fyne.Container)
		for i := 0; i < ldd; i++ {
			if reflect.TypeOf(box.Objects[i]) == reflect.TypeOf(widget.NewLabel("")) {
				lbl := box.Objects[i].(*widget.Label)
				lbl.SetText(gconv.String(rs[lii].GMap().GetOrSet((header)[i], "no data")))
			}
		}
		// 编辑
		box.Objects[ldd].(*widget.Button).OnTapped = func() {
			lst.Select(lii)
			frm := widget.NewForm()
			d := gmap.New()
			garray.NewStrArrayFrom(header).
				Iterator(func(k int, v string) bool {
					txt := widget.NewEntry()
					txt.SetText(gconv.String(rs[lii].GMap().GetOrSet((header)[k], "no data")))
					d.Set(v, txt)
					frm.Append(v, d.Get(v).(*widget.Entry))

					return true
				})
			frm.OnSubmit = func() {
				dmap := gmap.New()
				d.Iterator(func(k, v interface{}) bool {
					dmap.Set(k, strings.TrimSpace(v.(*widget.Entry).Text))
					return true
				})
				_, err := newDb.Model(tbl).Where((header)[0],
					gconv.String(rs[lii].GMap().Get((header)[0]))).Update(dmap)

				if err != nil {
					msg.SetText("update err " + err.Error())
					return
				}
				msg.SetText("update success")
			}

			w := fyne.CurrentApp().NewWindow("update record")
			w.Resize(fyne.NewSize(800, 700))
			w.SetContent(frm)
			w.Show()
		}
		// 删除
		box.Objects[ldd+1].(*widget.Button).OnTapped = func() {
			lst.Select(lii)
			d0 := gconv.String(rs[lii].GMap().Get((header)[0]))
			Confirm("Delete data", "Are you sure to delete "+d0, w,
				func() {
					if lii < 1 {
						msg.SetText("please select a record")
						return
					}
					_, err := newDb.Model(tbl).Delete((header)[0], d0)
					if err != nil {
						msg.SetText(err.Error())
						return
					}
					msg.SetText("delete" + d0)

					total, _ := newDb.Model(tbl).Count()
					bdTotal.Set(total)
				}, func() {
					msg.SetText("cancel delete")
				})
		}
	})

	return lst
}

// 用list显示gdb.Result
func RefreshListResult(lst *widget.List, newDb gdb.DB, tbl string, rs gdb.Result, msg *widget.Label, w fyne.Window) {
	if lst == nil {
		return
	}
	_, header := dbb.SqliteTblColsGF(newDb, tbl)
	ldd := len(header)
	lst.Length = func() int {
		return rs.Len()
	}
	lst.CreateItem = func() fyne.CanvasObject {
		hbox1 := container.NewGridWithColumns(ldd + 2)
		for i := 0; i < ldd; i++ {
			lbl := widget.NewLabelWithStyle("table", fyne.TextAlignCenter,
				fyne.TextStyle{})
			lbl.Wrapping = fyne.TextTruncate
			lbl.SetText((header)[i])
			hbox1.Add(lbl)
		}
		//hbox1.Add(PopUpBtn(nil, w))
		hbox1.Add(widget.NewButton("edit", nil))
		hbox1.Add(widget.NewButton("delete", nil))
		return hbox1
	}
	lst.UpdateItem = func(lii widget.ListItemID, co fyne.CanvasObject) {
		box := co.(*fyne.Container)
		for i := 0; i < ldd; i++ {
			if reflect.TypeOf(box.Objects[i]) == reflect.TypeOf(widget.NewLabel("")) {
				lbl := box.Objects[i].(*widget.Label)
				lbl.SetText(gconv.String(rs[lii].GMap().GetOrSet((header)[i], "no data")))
			}
		}
		// 编辑
		box.Objects[ldd].(*widget.Button).OnTapped = func() {
			lst.Select(lii)
			frm := widget.NewForm()
			d := gmap.New()
			garray.NewStrArrayFrom(header).
				Iterator(func(k int, v string) bool {
					txt := widget.NewEntry()
					txt.SetText(gconv.String(rs[lii].GMap().GetOrSet((header)[k], "no data")))
					d.Set(v, txt)
					frm.Append(v, d.Get(v).(*widget.Entry))

					return true
				})
			frm.Append("", widget.NewButton("Submit", func() {
				dmap := gmap.New()
				d.Iterator(func(k, v interface{}) bool {
					dmap.Set(k, strings.TrimSpace(v.(*widget.Entry).Text))
					return true
				})
				h0 := gconv.String(rs[lii].GMap().Get((header)[0]))
				_, err := newDb.Model(tbl).Where((header)[0], h0).
					Data(dmap).Update(dmap)

				if err != nil {
					msg.SetText("update err " + err.Error())
					return
				}

				menu.Glog.Info(newDb.GetCtx(), "Update record ", h0)
				msg.SetText("update success")
				rs, _ := newDb.Model(tbl).OrderDesc(header[0]).Limit(20).All()
				RefreshListResult(lstData, newDb, tbl, rs, msg, w)
			}))

			w := fyne.CurrentApp().NewWindow("update record")
			w.Resize(fyne.NewSize(800, 700))
			w.SetContent(frm)
			w.Show()
		}
		// 删除
		box.Objects[ldd+1].(*widget.Button).OnTapped = func() {
			lst.Select(lii)
			d0 := gconv.String(rs[lii].GMap().Get((header)[0]))
			Confirm("Delete data", "Are you sure to delete "+d0, w,
				func() {
					if lii < 0 {
						msg.SetText("please select a record")
						return
					}
					_, err := newDb.Model(tbl).Delete((header)[0], d0)
					menu.Glog.Info(newDb.GetCtx(), "Delete record ", d0)
					if err != nil {
						msg.SetText(err.Error())
						return
					}
					msg.SetText("delete" + d0)

					total, _ := newDb.Model(tbl).Count()
					bdTotal.Set(total)
				}, func() {
					msg.SetText("cancel delete")
				})
		}
	}
	lst.Refresh()
}

func lstHeader(header []string) fyne.CanvasObject {
	hbox1 := container.NewGridWithColumns(len(header))
	for i := 0; i < len(header); i++ {
		lbl := widget.NewLabelWithStyle("table", fyne.TextAlignCenter,
			fyne.TextStyle{})
		lbl.Wrapping = fyne.TextTruncate
		lbl.SetText(header[i])
		hbox1.Add(lbl)
	}
	//hbox1.Add(PopUpBtn(nil, w))
	hbox1.Add(widget.NewButton("edit", nil))
	hbox1.Add(widget.NewButton("delete", nil))
	return hbox1
}
